Análisis Exploratorio de Datos (EDA)

Análisis Exploratorio de Datos (EDA)#

import pandas as pd
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objs as go
from phik import phik_matrix
from numpy import log10, NaN
from seaborn import heatmap, set_theme
from json import load
from urllib.request import urlopen
from plotly.subplots import make_subplots

set_theme(style="ticks", context="talk", palette="tab10")
plt.rcParams.update({'font.size': 12})

Archivo GeoJSON para trazar los mapas:

with urlopen('https://gist.githubusercontent.com/john-guerra/43c7656821069d00dcbc/raw/be6a6e239cd5b5b803c6e7c2ec405b793a9064dd/Colombia.geo.json') as response:
    counties = load(response)
df = pd.read_parquet('Data/data_cleaned.parquet')
df_factorize = df.apply(lambda x : pd.factorize(x)[0]) 
df_corr = df_factorize.phik_matrix(interval_cols=list(df.columns)).copy()

Como podemos ver en el mapa de calor, hay una relación entre las columnas de género y grupo_etario.

import plotly.express as px

fig = px.imshow(df_corr.values,
                labels=dict(x="", y="", color="Correlación"),
                x=df_corr.columns,
                y=df_corr.columns,
                color_continuous_scale='RdBu')

fig.update_layout(title="Mapa de calor de correlación",
                  width=800,
                  height=600)

fig.show()

Distribución De los Datos:

import plotly.graph_objs as go
from plotly.subplots import make_subplots
import pandas as pd

num_columns = len(df.columns)
num_rows = num_columns // 2 if num_columns % 2 == 0 else (num_columns // 2) + 1

fig = make_subplots(rows=num_rows, cols=2, subplot_titles=df.columns)

for i, column in enumerate(df.columns):
    fig.add_trace(
        go.Histogram(x=df[column], nbinsx=50, name=column),
        row=(i // 2) + 1,
        col=(i % 2) + 1
    )
fig.update_layout(
    width=800,
    height=500 * num_rows,
    title_text="Histograms of DataFrame Columns"
)

fig.show()
df['cantidad'].describe(exclude='datetime')
count    274593.000000
mean          1.461381
std           1.549710
min           1.000000
25%           1.000000
50%           1.000000
75%           1.000000
max          19.000000
Name: cantidad, dtype: float64

Dadas estas estadísticas, se puede concluir que cantidad tiende a ser muy frecuentemente el valor 1, ya que la mediana y los tres primeros cuartiles son todos 1. Sin embargo, hay algunos valores mucho mayores, hasta 19, lo que explica la desviación estándar más grande y el promedio que es ligeramente superior a 1.

El departamento con más casos y su distribución:

table_department = df.groupby('departamento')['cantidad'].sum().reset_index()
table_department = table_department.rename(columns={'cantidad': 'total_cantidad'})
table_department_sorted = table_department.sort_values(by='total_cantidad', ascending=False)

print(table_department_sorted)
                                         departamento  total_cantidad
1                                           ANTIOQUIA           63336
26                              SANTAFE DE BOGOTA D.C           63294
14                                       CUNDINAMARCA           38084
30                                    VALLE DEL CAUCA           37855
27                                          SANTANDER           23006
6                                              BOYACA           15894
5                                             BOLIVAR           14508
4                                           ATLANTICO           14146
29                                             TOLIMA           13476
20                                               META           13310
21                                             NARIÑO           11707
10                                              CAUCA           11372
17                                              HUILA           10939
22                                 NORTE DE SANTANDER           10538
25                                          RISARALDA            8245
13                                            CORDOBA            7611
19                                          MAGDALENA            7315
11                                              CESAR            7249
7                                              CALDAS            6373
28                                              SUCRE            5205
24                                            QUINDIO            3192
9                                            CASANARE            3061
8                                             CAQUETA            2328
23                                           PUTUMAYO            1951
18                                         LA GUAJIRA            1874
2                                              ARAUCA            1418
12                                              CHOCO            1246
16                                           GUAVIARE             758
3   ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA...             753
31                                             VAUPES             362
0                                            AMAZONAS             340
15                                            GUAINIA             327
32                                            VICHADA             212
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\3368049774.py:1: FutureWarning:

The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
locs = table_department['departamento']
for loc in counties['features']:
    loc['id'] = loc['properties']['NOMBRE_DPT']

fig = make_subplots(
    rows=1, cols=2,
    subplot_titles=['Normal distribution', 'Logarithm 10'],
    specs=[[{"type": "mapbox"}, {"type": "mapbox"}]]
)

fig.add_trace(
    go.Choroplethmapbox(
        geojson=counties,
        locations=table_department['departamento'],
        z=table_department['total_cantidad'],
        colorbar_title='Casos',
        colorscale='YlOrRd',
        colorbar=dict(thickness=20, x=0.46),
        marker=dict(opacity=0.75)
    ),
    row=1, col=1
)

fig.add_trace(
    go.Choroplethmapbox(
        geojson=counties,
        locations=table_department['departamento'],
        z=log10(table_department['total_cantidad']),
        colorbar_title='Case count (Log10)',
        colorscale='YlOrRd',
        colorbar=dict(thickness=20, x=1.02),
        marker=dict(opacity=0.75)
    ),
    row=1, col=2
)

fig.update_layout(
    margin=dict(l=20, r=0, t=80, b=40),
    title='Casos de Violencia doméstica distribuidos en Colombia',
    mapbox1=dict(zoom=3.4, style='carto-positron', center={"lat": 4.570868, "lon": -74.2973328}),
    mapbox2=dict(zoom=3.4, style='carto-positron', center={"lat": 4.570868, "lon": -74.2973328})
)
fig.show()

Los casos en todo el país están concentrados en la parte central del país, como era de esperar debido a que una gran cantidad de población se encuentra en esta región.

El lado derecho del gráfico muestra una función logarítmica con base 10 aplicada a los valores del lado izquierdo del gráfico. Esto se hace únicamente con el propósito de mejorar la representación visual de cómo están distribuidos los casos en el país, y no refleja la distribución real de los datos.

Evolución de la Violencia Doméstica en Colombia

df_suma = df.groupby(pd.to_datetime(df['fecha_hecho']).dt.year)['cantidad'].sum().reset_index()
df_suma.columns = ['año', 'cantidad']

fig = px.line(df_suma, x='año', y='cantidad', title='Violencia Doméstica en Colombia', 
              hover_data={'año': True, 'cantidad': ':.0f'})

fig.update_xaxes(title='Año')
fig.update_yaxes(title='Cantidad de casos')
fig.show()

Scatter plot por regiones

def nueva_region(departamento):
    if departamento in ['AMAZONAS', 'CAQUETA', 'GUAINIA', 'VAUPES', 'GUAVIARE', 'PUTUMAYO']:
        return 'Amazónica'
    elif departamento in ['ANTIOQUIA', 'BOYACA', 'CALDAS', 'CUNDINAMARCA', 'SANTAFE DE BOGOTA D.C', 'HUILA', 'NORTE DE SANTANDER', 'QUINDIO', 'RISARALDA', 'SANTANDER', 'TOLIMA']:
        return 'Andina'
    elif departamento in ['VALLE DEL CAUCA', 'CHOCO', 'CAUCA', 'NARIÑO']:
        return 'Pacífica'
    elif departamento in ['ATLANTICO', 'BOLIVAR', 'CESAR', 'CORDOBA', 'LA GUAJIRA', 'MAGDALENA', 'SUCRE', 'ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA']:
        return 'Caribe'
    elif departamento in ['ARAUCA', 'CASANARE', 'META', 'VICHADA']:
        return 'Orinoquía'
    else:
        return 'Desconocido' 


df['region'] = df['departamento'].apply(nueva_region)
df['fecha_hecho'] = pd.to_datetime(df['fecha_hecho'])
df['mes'] = df['fecha_hecho'].dt.month
df['año'] = df['fecha_hecho'].dt.year

#Agrupar los datos por mes, año y región, sumando la cantidad de casos
df_suma = df.groupby(['año', 'mes', 'region'])['cantidad'].sum().reset_index()

fig = px.scatter(df_suma, x='mes', y='cantidad', color='region', hover_data=['region'], title='Evolución de la violencia en Colombia',
                 labels={'mes': 'Mes', 'cantidad': 'Cantidad de casos', 'region': 'Región'}, animation_frame='año')

#Slider de año
fig.update_layout(xaxis=dict(type='category'), yaxis=dict(range=[0, df_suma['cantidad'].max() * 1]))
fig.update_traces(marker=dict(size=10, opacity=0.8))
fig.show()

¿Qué tipo de arma es la más común?

gun_table = pd.pivot_table(df, index = 'armas_medios', values = 'cantidad', columns = None, aggfunc='count',sort=True).reset_index()
gun_table
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\4238805791.py:1: FutureWarning:

The default value of observed=False is deprecated and will change to observed=True in a future version of pandas. Specify observed=False to silence this warning and retain the current behavior
armas_medios cantidad
0 ARMA BLANCA 125532
1 ARMA DE FUEGO 892
2 DESCONOCIDA 51317
3 SIN EMPLEO DE ARMAS 96852
colors = ['skyblue', 'green', 'red', 'purple', 'orange']
gun_graph = px.bar(gun_table, x='armas_medios', y='cantidad', text_auto='.2s', title='Tipo de arma usada',color='armas_medios', color_discrete_sequence=colors )
gun_graph.update_traces(textfont_size=12, textangle=0, textposition="outside", cliponaxis=False)
gun_graph.update_xaxes(tickvals=[0, 1, 2, 3, 4], ticktext=['ARMA BLANCA', 'ARMA DE FUEGO', 'ESCOPOLAMINA ', 'SIN EMPLEO DE ARMAS ','DESCONOCIDA'])
gun_graph.show()

El tipo de arma más común utilizado en casos de violencia doméstica en Colombia es el arma blanca, seguida de sin empleo de armas. Es interesante ver cómo el arma blanca es mucho más utilizada que las otras, especialmente el arma de fuego y la escopolamina.

Distribución Por Género:

df.groupby('genero')['cantidad'].count()
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\706662510.py:1: FutureWarning:

The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
genero
FEMENINO     205516
MASCULINO     69077
Name: cantidad, dtype: int64
fig = px.pie(
    df, 
    names='genero', 
    values='cantidad', 
    title='Víctimas por Género'
)

fig.update_traces(textinfo='percent+label', textfont_size=14)
fig.show()

Se puede observar que el género Femenimo es el que más casos reporta con un 77.7%.

dfsex = pd.pivot_table(df, index = ('genero', 'armas_medios'), values = 'cantidad', columns = None, aggfunc='count', sort=True).reset_index()
dfsex
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\2537065515.py:1: FutureWarning:

The default value of observed=False is deprecated and will change to observed=True in a future version of pandas. Specify observed=False to silence this warning and retain the current behavior
genero armas_medios cantidad
0 FEMENINO ARMA BLANCA 95475
1 FEMENINO ARMA DE FUEGO 722
2 FEMENINO DESCONOCIDA 38105
3 FEMENINO SIN EMPLEO DE ARMAS 71214
4 MASCULINO ARMA BLANCA 30057
5 MASCULINO ARMA DE FUEGO 170
6 MASCULINO DESCONOCIDA 13212
7 MASCULINO SIN EMPLEO DE ARMAS 25638

Gráfico que compara cuántas víctimas hay por género, en términos del tipo de arma que se utilizó.

fig_sex = px.bar(dfsex, x='genero', y='cantidad', color='armas_medios', barmode='group', text_auto='.2s', 
                title="Género de las víctimas y el número de casos que involucran cada tipo de arma", 
                labels={'Cantidad':'Casos', 'genero':'Género y tipo de arma'}, height=400)

fig_sex.update_traces(textfont_size=12, textangle=0, textposition="outside", cliponaxis=False)
fig_sex.show()
  • Predominio del género masculino: Hay una cantidad significativamente mayor de víctimas de género femenino en comparación con el género masculino en los datos presentados. Esto es evidente por el tamaño total de las barras.

  • Arma blanca más frecuente: Para ambos géneros, el arma blanca parece ser el tipo de arma más comúnmente involucrado en los casos, ya que representa la mayor proporción en cada barra.

  • Menos frecuencia de escopolamina y casos con Arma de Fuego: La escopolamina y los casos ccasos con Arma de Fuego representan una menor proporción en comparación con las otras categorías, tanto para las víctimas femeninas como masculinas.

  • Casos sin empleo de armas: Es notable que una fracción considerable de los casos para las víctimas masculinas y femeninas.

Relación entre género y Grupo Etario:

df.groupby(['genero', 'grupo_etario'])['cantidad'].count()
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\758330160.py:1: FutureWarning:

The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
genero     grupo_etario
FEMENINO   ADOLESCENTES     11012
           ADULTOS         184625
           MENORES           9879
MASCULINO  ADOLESCENTES      5507
           ADULTOS          52803
           MENORES          10767
Name: cantidad, dtype: int64
dfsex_age = pd.pivot_table(df, index = ('genero', 'grupo_etario'), values = 'cantidad', columns = None, aggfunc='count', sort=True).reset_index()
dfsex_age
C:\Users\Andres\AppData\Local\Temp\ipykernel_9864\1976776229.py:1: FutureWarning:

The default value of observed=False is deprecated and will change to observed=True in a future version of pandas. Specify observed=False to silence this warning and retain the current behavior
genero grupo_etario cantidad
0 FEMENINO ADOLESCENTES 11012
1 FEMENINO ADULTOS 184625
2 FEMENINO MENORES 9879
3 MASCULINO ADOLESCENTES 5507
4 MASCULINO ADULTOS 52803
5 MASCULINO MENORES 10767

Como se observa aquí, la mayoría de los individuos afectados son mujeres adultas, mientras que hay poca variación en el número de menores afectados entre hombres y mujeres.

fig_sex_age = px.bar(dfsex_age, x='genero', y='cantidad', color='grupo_etario', barmode='group', text_auto='.2s', 
                    title="Género de las victimas y número de casos según la Edad", 
                    labels={'cantidad':'Casos', 'genero':'Género y Edad'}, height=400)

fig_sex_age.update_traces(textfont_size=12, textangle=0, textposition="outside", cliponaxis=False)
fig_sex_age.show()
  • El grupo de adultos tiene el mayor número de casos en comparación con los adolescentes y los menores para ambos géneros.

  • Hay una cantidad significativa de casos de adultos en el género femenino, más que en el masculino.

  • Mientras que para el género femenino los casos de adolescentes (barra azul) y menores (barra verde) son relativamente bajos en comparación con los adultos, hay una presencia notable de casos en el género masculino, especialmente en adolescentes.

Análisis de por Arma de Fuego:

df.head()
departamento municipio armas_medios fecha_hecho genero grupo_etario cantidad region mes año
0 ANTIOQUIA AMAGÁ ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019
1 ANTIOQUIA EL SANTUARIO ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019
2 ANTIOQUIA MEDELLÍN (CT) ARMA BLANCA 2019-01-01 MASCULINO ADULTOS 2 Andina 1 2019
3 ANTIOQUIA NARIÑO ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019
4 ATLANTICO BARRANQUILLA (CT) ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 3 Caribe 1 2019
dfsco = df.query('armas_medios == "ARMA DE FUEGO"')
dfsco
departamento municipio armas_medios fecha_hecho genero grupo_etario cantidad region mes año
619 NORTE DE SANTANDER CÚCUTA (CT) ARMA DE FUEGO 2019-01-05 FEMENINO ADULTOS 1 Andina 1 2019
731 TOLIMA IBAGUÉ (CT) ARMA DE FUEGO 2019-01-06 FEMENINO ADULTOS 1 Andina 1 2019
1575 ATLANTICO SOLEDAD ARMA DE FUEGO 2019-01-14 FEMENINO ADULTOS 1 Caribe 1 2019
1576 NARIÑO PASTO (CT) ARMA DE FUEGO 2019-01-14 FEMENINO ADULTOS 1 Pacífica 1 2019
1692 CASANARE YOPAL (CT) ARMA DE FUEGO 2019-01-15 FEMENINO ADULTOS 1 Orinoquía 1 2019
... ... ... ... ... ... ... ... ... ... ...
272896 CESAR VALLEDUPAR (CT) ARMA DE FUEGO 2023-02-15 FEMENINO ADULTOS 1 Caribe 2 2023
273358 ATLANTICO SOLEDAD ARMA DE FUEGO 2023-02-19 FEMENINO ADULTOS 1 Caribe 2 2023
273550 VALLE DEL CAUCA CANDELARIA ARMA DE FUEGO 2023-02-20 FEMENINO ADULTOS 1 Pacífica 2 2023
273689 CESAR VALLEDUPAR (CT) ARMA DE FUEGO 2023-02-21 FEMENINO ADULTOS 1 Caribe 2 2023
274483 META GRANADA ARMA DE FUEGO 2023-02-28 MASCULINO ADULTOS 1 Orinoquía 2 2023

892 rows × 10 columns

dfdsco = pd.pivot_table(dfsco, index='departamento', values='cantidad', aggfunc='count', observed=False).reset_index()

if isinstance(dfdsco['departamento'].dtype, pd.CategoricalDtype):
    new_categories = dfdsco['departamento'].cat.categories.tolist()
    replacement = {'ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA': 'SAN ANDRES'}
    new_categories = [replacement.get(item, item) for item in new_categories]
    dfdsco['departamento'] = dfdsco['departamento'].cat.rename_categories(new_categories)
else:
    dfdsco['departamento'] = dfdsco['departamento'].replace({
        'ARCHIPIELAGO DE SAN ANDRES PROVIDENCIA Y SANTA CATALINA': 'SAN ANDRES'
    })

Es cierto que el uso de ARMA DE FUEGO está concentrado principalmente en la región del Valle del Cauca.

fig = px.bar(dfdsco, x='cantidad', y='departamento', text_auto='.2s', 
            title="Número de informes de violencia familiar con Arma de Fuego por departamento", 
            labels={'departamento':'Departamento', 'cantidad':'Casos'}, orientation='h')

fig.update_traces(textfont_size=12, textangle=0, textposition="outside",cliponaxis=False)
fig.update_layout(width=1200, height=800)
fig.show()

Mapa de casos de Arma de Fuego distribuidos en el país, con la función logaritmo base 10 aplicada para visualizar mejor su distribución.

locs = dfdsco['departamento']
for loc in counties['features']:
    loc['id'] = loc['properties']['NOMBRE_DPT']

fig = go.Figure(go.Choroplethmapbox(
    geojson=counties,
    locations=locs,
    z=log10(dfdsco['cantidad']),
    colorscale='YlOrRd',
    colorbar_title="Número"
))

fig.update_layout(
    mapbox_style="carto-positron",
    mapbox_zoom=3.5,
    mapbox_center={"lat": 4.570868, "lon": -74.2973328},
    title='Casos de Arma de Fuego distribuidos en el país Log10'
)

fig.show()
C:\Users\Andres\psqlpy_venv\Lib\site-packages\pandas\core\arraylike.py:399: RuntimeWarning:

divide by zero encountered in log10

Análisis de Series de Tiempo:

df['day'] = df['fecha_hecho'].dt.day_name()
df['month'] = df['fecha_hecho'].dt.month_name()
df.head()
departamento municipio armas_medios fecha_hecho genero grupo_etario cantidad region mes año day month
0 ANTIOQUIA AMAGÁ ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019 Tuesday January
1 ANTIOQUIA EL SANTUARIO ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019 Tuesday January
2 ANTIOQUIA MEDELLÍN (CT) ARMA BLANCA 2019-01-01 MASCULINO ADULTOS 2 Andina 1 2019 Tuesday January
3 ANTIOQUIA NARIÑO ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 1 Andina 1 2019 Tuesday January
4 ATLANTICO BARRANQUILLA (CT) ARMA BLANCA 2019-01-01 FEMENINO ADULTOS 3 Caribe 1 2019 Tuesday January
new_order_month = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
new_order_day = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']

df_day = df.groupby('day')['cantidad'].sum().reindex(new_order_day, axis=0).reset_index()
df_month = df.groupby('month')['cantidad'].sum().reindex(new_order_month, axis=0).reset_index()
import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(rows=2, cols=1, subplot_titles=('Casos por mes', 'Casos por día de la semana'))

for i, (month, cases) in enumerate(zip(df_month['month'], df_month['cantidad'])):
    fig.add_trace(
        go.Bar(x=[month], y=[cases], text=[str(cases)], textposition='auto'),
        row=1, col=1
    )
    
for i, (day, cases) in enumerate(zip(df_day['day'], df_day['cantidad'])):
    fig.add_trace(
        go.Bar(x=[day], y=[cases], text=[str(cases)], textposition='auto'),
        row=2, col=1
    )

fig.update_xaxes(title_text="Meses", row=1, col=1, tickangle=25)
fig.update_yaxes(title_text="Casos", row=1, col=1)

fig.update_xaxes(title_text="Días de la semana", row=2, col=1, tickangle=25)
fig.update_yaxes(title_text="Casos", row=2, col=1)

fig.update_layout(height=800, showlegend=False)
fig.show()

Podemos observar cómo los casos por mes tienen una tendencia estable, excepto en diciembre, este mes tiene una disminución abrupta que puede deberse a las festividades celebradas durante esta época del año.

Asimismo, los domingos, que es el día de descanso en Colombia, es el día con el mayor número de casos de la semana.

df_date1 = df.groupby('fecha_hecho')['cantidad'].sum().reset_index()

df_date2 = df.groupby(df.fecha_hecho.dt.year)['cantidad'].sum().reset_index()
df_date2 = df_date2.rename({'fecha_hecho':'year'}, axis=1)
fig = make_subplots(rows=3, cols=1, vertical_spacing=0.1, subplot_titles=(
    'Timeline de casos diarios',
    'Total de casos agrupados por año',
    'Distribución de casos diarios desde 2019 hasta 2022'
))

fig.add_trace(
    go.Scatter(x=df_date1['fecha_hecho'], y=df_date1['cantidad'], mode='lines+markers', name='Casos Diarios', line=dict(color='blue')),
    row=1, col=1
)

fig.add_trace(
    go.Bar(x=df_date2['year'], y=df_date2['cantidad'], name='Casos por Año', marker=dict(color='green')),
    row=2, col=1
)

df_date1_filtered = df_date1[df_date1['fecha_hecho'] > '2019-01-01']
fig.add_trace(
    go.Scatter(x=df_date1_filtered['fecha_hecho'], y=df_date1_filtered['cantidad'], mode='lines+markers', name='Casos desde 2019', line=dict(color='red')),
    row=3, col=1
)

fig.update_xaxes(title_text="Fecha", row=1, col=1)
fig.update_yaxes(title_text="Casos", row=1, col=1)
fig.update_xaxes(title_text="Años", row=2, col=1)
fig.update_yaxes(title_text="Casos", row=2, col=1)
fig.update_xaxes(title_text="Fecha", row=3, col=1)
fig.update_yaxes(title_text="Casos", row=3, col=1)

fig.update_layout(height=800, showlegend=False)

fig.show()

Se puede concluir a partir de los gráficos anteriores que cada fin de diciembre y principio de enero, durante las vacaciones en Colombia, hay un aumento en los casos reportados. Esto ocurre todos los años en todo el país.